﻿using System;
using System.Web;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Security.Policy;
using System.IO;
using System.Reflection;
using System.Web.Mvc;
using DialectSoftware.Networking;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using WebFabricator.org.Management;


namespace WebFabricator.org.Storage
{
    //TODO: Centralize Normalize remote scheme?
    //TODO: Add cache semantics
    public class UriStore : MarshalByRefObject, IUriStore
    {
        SLSMPServer server;

        [Import(typeof(IPersistentStorage))]
#pragma warning disable 0649
        IPersistentStorage storage;
#pragma warning restore 0649

        public static IUriStore Instance
        {
            get;
            set;
        }

        public static void Initialize(object owner)
        {
            if (Instance == null)
            {
                Instance = UriStorageProviderAttribute.CreateLocalStore(owner.GetType());
            }
        }

        public UriStore()
        {
            try
            {
                Id = AppDomain.CurrentDomain.FriendlyName;
                server = new SLSMPServer();
                server.OnHelo += new Helo(OnHelo);
                server.ListenBegin();

                DirectoryCatalog catalog = new DirectoryCatalog(Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), "bin"));
                CompositionContainer container = new CompositionContainer(catalog);
                container.ComposeParts(this);
            }
            catch (ReflectionTypeLoadException tle)
            {
                throw new Exception(tle.LoaderExceptions.Aggregate<Exception, string>(String.Format("{0} {1}", tle.Message, AppDomain.CurrentDomain.BaseDirectory), (message, ex) =>
                {
                    return String.Join("\r\n",message, ex.ToString());
                }),tle);
            }
            catch (Exception e)
            {
                throw new Exception(String.Format("{0} {1}", e.ToString(), AppDomain.CurrentDomain.BaseDirectory) , e);
            }
        }
     
        private HELOResult OnHelo()
        {
            HELOResult result = new HELOResult();
            result.Machine = Environment.MachineName;
            result.Designation = "UNKOWN";
            result.Instances = new[] { Id };
            return result;
        }

        public Uri this[Uri uri]
        {
            get
            {
                if (Contains(uri))
                {
                    return storage[uri];
                }
                else
                {
                    throw new HttpException(404, uri.ToString());
                }
            }
            set
            {
                storage[uri] = value;
            }
        }

        public bool Contains(Uri uri)
        {
            return storage.ContainsKey(uri);
        }

        public void Remove(Uri uri)
        {
            storage.Remove(uri);
        }

        public void Clear()
        {
            storage.Clear();
        }

        public static void UnInitialize()
        {
            if(Instance != null)
                Instance.Dispose();
        }

        public virtual void Dispose()
        {
            if(storage is IDisposable)
                ((IDisposable)storage).Dispose();
        }

        public IEnumerator<Url> GetEnumerator()
        {
            return this.storage.Keys.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.storage.Keys.GetEnumerator();
        }

        public string Id
        {
            get;
            set;
        }
    }
}


